﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Input;

namespace DualityEngine.Business.Camera
{
    public class SpectatorCamera : Camera
    {
        private Quaternion camerarotation;

        public SpectatorCamera() 
            : base()
        {
            float viewAngle = MathHelper.PiOver4;
            float nearPlane = 0.5f;
            float farPlane = 200000.0f;
            this.projectionmatrix = Matrix.CreatePerspectiveFieldOfView(viewAngle, aspectRatio, nearPlane, farPlane);
            this.camerarotation = Quaternion.Identity;
            UpdateViewMatrix();
        }

        public override void Update(GameTime gameTime)
        {
            base.Update(gameTime);

            float updownRotation = 0.0f;
            float leftrightRotation = 0.0f;
            KeyboardState keys = Keyboard.GetState();
            MouseState mousestate = Mouse.GetState();

            if(keys.IsKeyDown(Keys.W))
            {
                AddToCameraPosition(new Vector3(0, 0, -300));
            }
            if (keys.IsKeyDown(Keys.S))
            {
                AddToCameraPosition(new Vector3(0, 0, 300));
            }
            if (keys.IsKeyDown(Keys.A))
            {
                AddToCameraPosition(new Vector3(-300, 0, 0));
            }
            if (keys.IsKeyDown(Keys.D))
            {
                AddToCameraPosition(new Vector3(300, 0, 0));
            }
            if(mousestate.LeftButton == ButtonState.Pressed)
            {
                if (mousestate.X < ResourceManager.Instance.graphicsdevice.PresentationParameters.BackBufferWidth / 2)
                {
                    double factor = (double)(ResourceManager.Instance.graphicsdevice.PresentationParameters.BackBufferWidth / 2) / (mousestate.X + (ResourceManager.Instance.graphicsdevice.PresentationParameters.BackBufferWidth / 2));
                    leftrightRotation = (float)factor * 0.05f;
                }
                else if (mousestate.X > ResourceManager.Instance.graphicsdevice.PresentationParameters.BackBufferWidth / 2)
                {
                    double factor = (double)(mousestate.X - (ResourceManager.Instance.graphicsdevice.PresentationParameters.BackBufferWidth / 2)) / (ResourceManager.Instance.graphicsdevice.PresentationParameters.BackBufferWidth / 2);
                    leftrightRotation = -((float)factor * 0.05f);
                }
                if (mousestate.Y > ResourceManager.Instance.graphicsdevice.PresentationParameters.BackBufferHeight / 2)
                {
                    double factor = (double)(ResourceManager.Instance.graphicsdevice.PresentationParameters.BackBufferHeight / 2) / (mousestate.Y + (ResourceManager.Instance.graphicsdevice.PresentationParameters.BackBufferHeight / 2));
                    updownRotation = -(float)factor * 0.05f;
                }
                else if (mousestate.Y < ResourceManager.Instance.graphicsdevice.PresentationParameters.BackBufferHeight / 2)
                {
                    double factor = (double)(mousestate.Y - (ResourceManager.Instance.graphicsdevice.PresentationParameters.BackBufferHeight / 2)) / (ResourceManager.Instance.graphicsdevice.PresentationParameters.BackBufferHeight / 2);
                    updownRotation = (float)factor * 0.05f;
                }
            }
            //Mouse.SetPosition(ResourceManager.Instance.resolutionwidth / 2, ResourceManager.Instance.resolutionheight / 2);

            Quaternion additionalRotation = Quaternion.CreateFromAxisAngle(new Vector3(1, 0, 0), updownRotation) * Quaternion.CreateFromAxisAngle(new Vector3(0, 1, 0), leftrightRotation);
            camerarotation = camerarotation * additionalRotation;
            UpdateViewMatrix();
        }

        private void AddToCameraPosition(Vector3 vectorToAdd)
        {
            float moveSpeed = 0.05f;
            Vector3 rotatedVector = Vector3.Transform(vectorToAdd, camerarotation);
            cameraposition += moveSpeed * rotatedVector;
            UpdateViewMatrix();
        }

        private void UpdateViewMatrix()
        {
            Vector3 cameraOriginalTarget = new Vector3(0, 0, -1);
            Vector3 cameraOriginalUpVector = new Vector3(0, 1, 0);
            Vector3 cameraRotatedTarget = Vector3.Transform(cameraOriginalTarget, camerarotation);
            Vector3 cameraFinalTarget = cameraposition + cameraRotatedTarget;
            Vector3 cameraRotatedUpVector = Vector3.Transform(cameraOriginalUpVector, camerarotation);
            this.viewmatrix = Matrix.CreateLookAt(cameraposition, cameraFinalTarget, cameraRotatedUpVector);
        }
    }
}
